#include "GameObject.h"
#include "Camera.h"
#include "InputManager.h"

extern Camera* camera;

GameObject::GameObject(void)
{
	shader = NULL;
}

void GameObject::Init()
{
	position = Vector3(0.0f, -1.0f, -5.0f);
	scale = Vector3(1.0f, 1.0f, 1.0f);
	rotation = Vector3(1.0f, 1.0f, 1.0f);
}

void GameObject::Rotation()
{
	rotation.x -= 0.03f;
}

void GameObject::Update()
{
	mvpMatrix = GetWorldMatrix() * camera->GetViewMatrix() * camera->GetProjectMatrix();
}

void GameObject::Render()
{
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glUseProgram(shader->program);
	for (int i = 0; i < model->GetNumberOfParts(); i++)
	{
		glBindBuffer(GL_ARRAY_BUFFER, this->model->GetVboId1()[i]);

		if(shader->a_positionLoc != -1)
		{
			glEnableVertexAttribArray(shader->a_positionLoc);
			glVertexAttribPointer(shader->a_positionLoc, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *) offsetof(Vertex, position));
		}

		if(shader->a_uvLoc != -1)
		{
			glEnableVertexAttribArray(shader->a_uvLoc);
			glVertexAttribPointer(shader->a_uvLoc, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *) offsetof(Vertex, uv));
		}

		if (shader->a_colorLoc != -1)
		{
			glEnableVertexAttribArray(shader->a_colorLoc);
			glVertexAttribPointer(shader->a_colorLoc, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *) offsetof(Vertex, color));
		}

		for(GLuint j = 0; j < textureID.size(); j++)
		{
			if(shader->u_texture[j] != -1)
			{
				glActiveTexture(GL_TEXTURE0 + j);
				glBindTexture(GL_TEXTURE_2D, textureID[j][i]);
				glUniform1i(shader->u_texture[j], j);
			}
		}

		if(shader->u_fireLoc != -1){
			GLfloat framePerSecond = Timer::GameTime() / 50.0f;
			glUniform1f(shader->u_fireLoc, framePerSecond);

			glEnable(GL_BLEND);
			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		}

		if(shader->u_cubeLoc != -1)
		{
			glActiveTexture(GL_TEXTURE1);
			glBindTexture(GL_TEXTURE_CUBE_MAP, this->cubeID);
			glUniform1i(shader->u_cubeLoc, 1);
		}

		if(shader->a_normLoc != -1){
			glEnableVertexAttribArray(shader->a_normLoc);
			glVertexAttribPointer(shader->a_normLoc, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *) offsetof(Vertex, normal));
		}

		if(shader->u_cameraLoc != -1){
			glUniform3f(shader->u_cameraLoc, camera->GetPosition().x, camera->GetPosition().y, camera->GetPosition().z);
		}
		if(shader->u_WLoc!= -1){
			glUniformMatrix4fv(shader->u_WLoc, 1, GL_FALSE, (float*) GetWorldMatrix().m);
		}

		if ( shader->u_wvpLoc != -1 )
		{
			glUniformMatrix4fv(shader->u_wvpLoc, 1, GL_FALSE,(float*) &mvpMatrix);
		}

		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->model->GetIboId1()[i]);
	    glDrawElements(GL_TRIANGLES, this->model->GetIndexSize()[i], GL_UNSIGNED_INT, 0);

		//========================================	
		glBindBuffer(GL_ARRAY_BUFFER, 0);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
		glBindTexture(GL_TEXTURE_2D, 0);
		glDisable(GL_BLEND);
	}
	glDisable(GL_DEPTH_TEST);
}

Matrix GameObject::GetWorldMatrix()
{
	Matrix translationMatrix;
	Matrix scaleMatrix;
	Matrix rotateX, rotateY, rotateZ;

	translationMatrix.SetTranslation(position);
	rotateX.SetRotationX(rotation.x);
	rotateY.SetRotationY(rotation.y);
	rotateZ.SetRotationZ(rotation.z);	
	scaleMatrix.SetScale(scale);

	Matrix worldMatrix = scaleMatrix * (rotateZ * rotateX * rotateY) * translationMatrix;

	return worldMatrix;
}

void GameObject::SetPosition(Vector3 position)
{
	this->position = position;
}

void GameObject::SetRotation(Vector3 rotation)
{
	this->rotation = rotation;
}

void GameObject::SetScale(Vector3 scale)
{
	this->scale = scale;
}

void GameObject::AddTexture(GLuint *_textureID)
{
	textureID.push_back(_textureID);
}

void GameObject::SetCubeID(GLuint _cubeID)
{
	this->cubeID = _cubeID;
}

void GameObject::SetShader(Shader* _shader)
{
	this->shader = _shader;
}

void GameObject::CoppyGameObject(GameObject *gameObject)
{
	//gameObject-SetPos
	//gameObject->SetShader(this->GetShader());
	//gameObject->Init(this->GetPosition(),this->GetRotation(),this->GetScale());
	//gameObject->SetTexture2D(m_texture2D, m_nTexture2D);
	//gameObject->(this->GetModel());
	shader = gameObject->GetShader();
	model = gameObject->GetModel();
	//AddTexture(18);
	Init();
}
MyBox GameObject::GetBox()
{
	Vector4 vecMin = Vector4(boxObject.xMin, boxObject.yMin, boxObject.zMin, 1.0) * GetWorldMatrix();
	Vector4 vecMax = Vector4(boxObject.xMax, boxObject.yMax, boxObject.zMax, 1.0) * GetWorldMatrix();

	MyBox boxPosition;

	if(vecMin.x < vecMax.x)
	{
		boxPosition.xMin = vecMin.x;
		boxPosition.xMax = vecMax.x;
	}
	else
	{
		boxPosition.xMin = vecMax.x;
		boxPosition.xMax = vecMin.x;
	}

	if(vecMin.y < vecMax.y)
	{
		boxPosition.yMin = vecMin.y;
		boxPosition.yMax = vecMax.y;
	}
	else
	{
		boxPosition.yMin = vecMax.y;
		boxPosition.yMax = vecMin.y;
	}

	if(vecMin.z < vecMax.z)
	{
		boxPosition.zMin = vecMin.z;
		boxPosition.zMax = vecMax.z;
	}
	else
	{
		boxPosition.zMin = vecMax.z;
		boxPosition.zMax = vecMin.z;
	}

	return boxPosition;
}

Vector3 GameObject::GetPosition()
{
	return position;
}

Model* GameObject::GetModel()
{
	return model;
}
Shader* GameObject::GetShader()
{
	return shader;
}


GameObject::~GameObject(void)
{
	//for (GLuint i = 0; i < textureID.size(); i++)
	//{
	//	SAFE_DEL_ARRAY(textureID[i]);
	//}
	//textureID.clear();
}